<template>
  <!-- <div ref="anchor" class="anchor-wrapper" :style="{ top: anchorPosition.top, left: anchorPosition.left}"> -->
  <div :ref="anchorRef" class="anchor-wrapper" :style="{ top: ytop+'%', left: xleft+'%' }">
    <anchor-tree :title-list="titleList" @locateTitle="handleLocateTitle" />
    <div class="acitve-anchor-circle" :style="{top: activeAnchorTop + 'px', left: '13px'}" />
  </div>
</template>

<script>
import AnchorTree from './anchorTree.js'
import { EventListener, nestToSimple, getRelativePosition } from './utils.js'
export default {
  name: 'Anchor',
  provide() {
    return {
      anchor: this
    }
  },
  components: {
    AnchorTree
  },
  props: {
    // 默认严格的，如果不严格，则按进度条百分比计算
    type: {
      type: String,
      default: 'strict'
    },
    ytop: {
      type: Number,
      default: 0
    },
    xleft: {
      type: Number,
      default: 0
    },
    // 标题列表
    titleList: {
      type: Array,
      default: () => []
    },
    // 相对于外层容器的位置
    position: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      anchorRef: 'anchorRef' + Math.floor(Math.random() * 1000000),
      container: null,
      scrollContainer: null,
      scrollEle: null,
      allTitleOffsetTop: [],
      currentAnchorId: null,
      initoffsetTop: 0,
      initscrollTop: 0,
      scrollRange: 0,
      pyTom: 0,
      activeAnchorTop: 0,
      anchorPosition: {
        left: 0,
        top: 0
      }
    }
  },
  computed: {
    simpleTitleList() {
      return this.nestToSimple(this.titleList)
    }
  },
  mounted() {
    // this.container = this.$refs[this.anchorRef].parentElement.parentElement.parentElement.parentElement.parentElement;
    this.container = this.findContainer(this.$refs[this.anchorRef], 'el-dialog__body')

    console.dir(this.container)
    this.getScrollObj()
    EventListener.add(this.scrollContainer, 'scroll', this.handleScroll)
    this.computedAnchorPosition()
    EventListener.add(window, 'scroll', this.handleWindowScroll)
    this.currentAnchorId = this.simpleTitleList[0].id

    // 计算初始节点的offset top , scroll top
    const initposition = document.querySelector(`#${this.currentAnchorId}`)
    this.initscrollTop = initposition.scrollTop
    this.initoffsetTop = initposition.offsetTop
    // this.pyTom = initposition.

    // 计算scroll 可移动的范围
    this.scrollRange = initposition.parentElement.offsetHeight - this.scrollContainer.offsetHeight
    this.setActiveAnchorCirclePosition()
  },
  beforeDestroy() {
    EventListener.remove(window, 'scroll', this.handleWindowScroll)
    EventListener.remove(this.scrollContainer, 'scroll', this.handleScroll)
  },
  methods: {
    /**
     * 递归查找上层Container
     * @param dom 原dom
     * @param clz 目标的class
     */
    findContainer(dom, clz) {
      // console.dir(dom.parentElement);
      if (dom.parentElement) {
        if (dom.parentElement.className.indexOf(clz) > -1) {
          return dom.parentElement
        } else {
          return this.findContainer(dom.parentElement, clz)
        }
      }
    },
    nestToSimple,
    // 滚动内容在浏览器可视区域时对应的锚点导航才可以在可视区域
    handleWindowScroll() {
      this.computedAnchorPosition()
    },
    // 计算锚点导航位置
    computedAnchorPosition() {
      this.anchorPosition.top = this.container
        ? `${this.position.top || 100 + this.scrollEle.offsetTop - (document.documentElement || document.body).scrollTop}px`
        : `${this.position.top || 100 + this.scrollEle.offsetTop}px`
      this.anchorPosition.left = `calc(${this.scrollEle.offsetLeft + this.scrollEle.offsetWidth}px - ${this.position.right || 200}px)`
    },
    // 获取滚动内容的外层容器对象及DOM
    getScrollObj() {
      if (this.container) {
        this.scrollContainer = this.container
        this.scrollEle = this.scrollContainer
      } else {
        this.scrollContainer = window
        this.scrollEle = document.documentElement || document.body
      }
    },
    // 点击锚点将页面定位对应的标题处，并改变路径hash值
    handleLocateTitle(data) {
      this.getAllTitleOffsetTop()
      const titleEle = document.querySelector(`#${data.id}`)
      // 获取该节点的offsetTop
      setTimeout(() => {
        this.currentAnchorId = data.id
        this.moveToAnchor(titleEle.offsetTop).then(() => {
          this.setActiveAnchorCirclePosition()
        })
        // this.setUrlHash(this.currentAnchorId)
      })
    },
    moveToAnchor(targetOffsetTop) {
      return new Promise((resolve, reject) => {
        let range = targetOffsetTop - this.initoffsetTop + this.initscrollTop
        if (range > this.scrollRange) {
          range = this.scrollRange
        }
        this.scrollContainer.scrollTop = range
        this.getCurrentAnchor(range)
        resolve()
      })
    },
    // 设置路径hash
    setUrlHash(hash) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          const location = window.location
          window.location.href = `${location.origin}${location.pathname}${location.search}#${hash}`
          resolve()
        }, 200)
      })
    },
    // 监听滚动过程中做了两件事：
    // 1、改变当前激活的锚点
    // 2、监听当前激活锚点变化并改变路径hash
    handleScroll(e) {
      this.getAllTitleOffsetTop()
      // const scrollTop = this.scrollContainer === window ? document.documentElement.scrollTop || document.body.scrollTop : e.target.scrollTop
      this.handlingScroll(e.target.scrollTop)
    },

    handlingScroll(scrollTop) {
      this.getCurrentAnchor(scrollTop)
      this.computedAnchorPosition()
    },

    // 获取所有锚点对应标题在滚动内容区域中距离顶部的距离
    getAllTitleOffsetTop() {
      this.allTitleOffsetTop = []
      let i = 0
      // 获取 初始卷动的距离 以及 卷动的总距离
      this.initscrollTop = document.getElementById(this.simpleTitleList[0].id).scrollTop
      this.initoffsetTop = document.getElementById(this.simpleTitleList[0].id).offsetTop
      this.scrollRange = document.getElementById(this.simpleTitleList[0].id).parentElement.offsetHeight - this.scrollContainer.offsetHeight

      const len = this.simpleTitleList.length
      while (i < len) {
        const elmnt = document.getElementById(this.simpleTitleList[i].id)
        const range = elmnt.offsetTop - this.initoffsetTop + this.initscrollTop
        // console.log('☆☆☆☆', elmnt.offsetTop, this.initoffsetTop, this.initscrollTop, this.scrollRange, range, '☆☆☆☆');
        if (this.type === 'unstrict') {
          this.allTitleOffsetTop.push(this.initscrollTop + (this.scrollRange - this.initscrollTop) * i / len)
        } else {
          this.allTitleOffsetTop.push(range > this.scrollRange ? this.scrollRange : range)
        }
        i++
      }
    },
    // 根据内容滚动距离获取当前锚点数据
    getCurrentAnchor(scrollTop) {
      // scrollTop 卷动的距离
      let i = -1
      const len = this.simpleTitleList.length
      while (++i < len) {
        const curAnchorScrollTop = this.allTitleOffsetTop[i]
        const nextAnchorScrollTop = this.allTitleOffsetTop[i + 1]
        if (scrollTop >= curAnchorScrollTop && !nextAnchorScrollTop) {
          this.currentAnchorId = this.simpleTitleList[i].id
          break
        } else if (scrollTop >= curAnchorScrollTop && (nextAnchorScrollTop && scrollTop < nextAnchorScrollTop)) {
          this.currentAnchorId = this.simpleTitleList[i].id
          break
        }
      }
      this.setActiveAnchorCirclePosition()
    },
    // 设置表示当前激活锚点的小球的位置
    setActiveAnchorCirclePosition() {
      // console.log('setActiveAnchorCirclePosition');
      this.$nextTick(() => {
        const currentAnchorEl = this.$refs[this.anchorRef].querySelector('.anchor-item-wrapper.is-active')
        // console.dir(currentAnchorEl);
        // console.log(getRelativePosition(currentAnchorEl, this.$refs[this.anchorRef]).y, currentAnchorEl.clientHeight / 2);
        if (currentAnchorEl) {
          this.activeAnchorTop = getRelativePosition(currentAnchorEl, this.$refs[this.anchorRef]).y + currentAnchorEl.clientHeight / 2
        }
      })
    }
  }
}
</script>
